<template>
  <div class="ui-calendar-month">
    <div class="ui-calendar-month__header">
      <span v-for="day in lang.days.initials">{{ day }}</span>
    </div>

    <div
      class="ui-calendar-month__week is-current"
      ref="current"

      :class="weekClasses"

      @transitionend="onTransitionEnd"
    >
      <ui-calendar-week
        :date-filter="dateFilter"
        :key="index"
        :max-date="maxDate"
        :min-date="minDate"
        :month="currentWeekStartDates[1].getMonth()"
        :selected="selected"
        :week-start="date"

        @date-select="onDateSelect"

        v-for="(date, index) in currentWeekStartDates"
      ></ui-calendar-week>
    </div>

    <div class="ui-calendar-month__week is-other" ref="other" :class="weekClasses">
      <ui-calendar-week
        :key="index"
        :max-date="maxDate"
        :min-date="minDate"
        :month="otherWeekStartDates[1].getMonth()"
        :selected="selected"
        :visible="false"
        :week-start="date"

        @date-select="onDateSelect"

        v-for="(date, index) in otherWeekStartDates"
      ></ui-calendar-week>
    </div>
  </div>
</template>

<script>
import UiCalendarWeek from './UiCalendarWeek.vue'

import dateUtils from './helpers/date'

export default {
  name: 'ui-calendar-month',

  props: {
    lang: Object,
    dateFilter: Function,
    dateInView: Date,
    selected: Date,
    maxDate: Date,
    minDate: Date
  },

  data () {
    return {
      dateOutOfView: dateUtils.clone(this.dateInView),
      isSliding: false,
      slideDirection: '',

      // Detects IE and not Edge: http://stackoverflow.com/a/22082397
      isIE: Boolean(window.MSInputMethodContext) && Boolean(document.documentMode),
      ieTimeout: null
    }
  },

  computed: {
    weekClasses () {
      return [
        { [`ui-calendar-month--slide-${this.slideDirection}`]: this.isSliding },
        { 'is-sliding': this.isSliding }
      ]
    },

    currentWeekStartDates () {
      return this.getWeekStartDates(this.dateInView)
    },

    otherWeekStartDates () {
      return this.getWeekStartDates(this.dateOutOfView)
    }
  },

  methods: {
    getWeekStartDates (dateInWeek) {
      let date = dateUtils.clone(dateInWeek)

      date.setDate(1) // Jump to the start of the month
      date = dateUtils.moveToDayOfWeek(date, 0) // Jump to the start of the week

      const current = dateUtils.clone(date)
      current.setDate(current.getDate() + 7)

      const starts = [date]
      const month = current.getMonth()

      while (current.getMonth() === month) {
        starts.push(dateUtils.clone(current))
        current.setDate(current.getDate() + 7)
      }

      return starts
    },

    goToDate (date, options = { isForward: true }) {
      this.isSliding = true
      this.slideDirection = options.isForward ? 'left' : 'right'
      this.dateOutOfView = dateUtils.clone(date)

      // A hack for IE: sometimes when rapidly scrolling through months, the
      // transitionend event is not fired, causing the month to not change.
      // This ensures that onTransitionEnd() is called after 300ms.
      if (this.isIE) {
        this.ieTimeout = setTimeout(this.onTransitionEnd, 300)
      }
    },

    onDateSelect (date) {
      this.$emit('date-select', date)
    },

    onTransitionEnd () {
      if (this.ieTimeout) {
        clearTimeout(this.ieTimeout)
        this.ieTimeout = null

        // Abort if the transition has already ended
        if (!this.isSliding) {
          return
        }
      }

      this.isSliding = false
      this.slideDirection = ''

      this.$emit('change', dateUtils.clone(this.dateOutOfView))
      this.$emit('transition-end')
    }
  },

  components: {
    UiCalendarWeek
  }
}
</script>

<style lang="scss">
@import './styles/imports';

.ui-calendar-month {
  height: ($ui-calendar-cell-size * 6) + $ui-calendar-month-header-height;
  overflow: hidden;
  position: relative;
  width: 100%;
}

.ui-calendar-month__header {
  align-items: center;
  display: flex;
  height: $ui-calendar-month-header-height;
  justify-content: space-around;
  width: 100%;

  span {
    align-items: center;
    color: $secondary-text-color;
    display: flex;
    font-size: rem-calc(14px);
    height: $ui-calendar-cell-size;
    justify-content: center;
    text-transform: uppercase;
    width: $ui-calendar-cell-size;
  }
}

.ui-calendar-month__week {
  $week-width: $ui-calendar-cell-size * 7;
  position: absolute;
  width: $week-width;

  &.is-current {
    left: 0;
  }

  &.is-other {
    left: $week-width;

    &.ui-calendar-month--slide-right {
      left: -$week-width;
    }
  }

  &.is-sliding {
    transition: transform 250ms ease;

    &.ui-calendar-month--slide-left {
      transform: translate3d(-$week-width, 0, 0);
    }

    &.ui-calendar-month--slide-right {
      transform: translate3d($week-width, 0, 0);
    }
  }
}
</style>s
